/*
 * Copyright (c) 2020-2099 the original author or authors. All rights reserve.
 */
package org.tianyun.cloud.mybatis.plugins.utils;

import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.mapping.ResultMapping;
import org.apache.ibatis.session.Configuration;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @auther ebert_chan
 */
public class MappedStatementUtils {

    public static final Lock LOCK = new ReentrantLock();

    public static MappedStatement getCopyMappedStatement(Configuration configuration, MappedStatement mappedStatement, String statementId) {
        MappedStatement ms = MappedStatementUtils.getMappedStatement(configuration, statementId);
        if (ms != null) {
            return ms;
        }
        try {
            LOCK.lock();
            ms = MappedStatementUtils.getMappedStatement(configuration, statementId);
            if (ms != null) {
                return ms;
            }

            ms = MappedStatementUtils.copyMappedStatement(mappedStatement, statementId);
            configuration.addMappedStatement(ms);
        } finally {
            LOCK.unlock();
        }
        return ms;
    }

    public static MappedStatement getMappedStatement(Configuration configuration, String id) {
        MappedStatement ms = null;
        try {
            ms = configuration.getMappedStatement(id, false);
        } catch (IllegalArgumentException e) {
            // do nothing
        }
        return ms;
    }

    public static MappedStatement copyMappedStatement(MappedStatement mappedStatement, String statementId) {
        MappedStatement.Builder builder = new MappedStatement.Builder(mappedStatement.getConfiguration(), statementId, mappedStatement.getSqlSource(),
                mappedStatement.getSqlCommandType());
        builder.resource(mappedStatement.getResource());
        builder.fetchSize(mappedStatement.getFetchSize());
        builder.statementType(mappedStatement.getStatementType());
        builder.keyGenerator(mappedStatement.getKeyGenerator());
        if (mappedStatement.getKeyProperties() != null && mappedStatement.getKeyProperties().length != 0) {
            StringBuilder keyProperties = new StringBuilder();
            for (int i = 0; i < mappedStatement.getKeyProperties().length; i++) {
                if (i > 0) {
                    keyProperties.append(",");
                }
                keyProperties.append(mappedStatement.getKeyProperties()[i]);
            }
            builder.keyProperty(keyProperties.toString());
        }
        builder.timeout(mappedStatement.getTimeout());
        builder.parameterMap(mappedStatement.getParameterMap());

        List<ResultMap> resultMaps = new ArrayList<ResultMap>();
        ResultMap resultMap = new ResultMap.Builder(mappedStatement.getConfiguration(), mappedStatement.getId(), Long.class, new ArrayList<ResultMapping>(0)).build();
        resultMaps.add(resultMap);
        builder.resultMaps(resultMaps);

        builder.resultSetType(mappedStatement.getResultSetType());
        builder.cache(mappedStatement.getCache());
        builder.flushCacheRequired(mappedStatement.isFlushCacheRequired());
        builder.useCache(mappedStatement.isUseCache());
        return builder.build();
    }

}
